

#include "parser.h"
#include <sstream>
#include <QtGlobal> // for asserts
#include <QString>

Node* Parser::parseThis(string inPut) {
    // save string for later reference
    toParse = inPut;
    
    // make a new stream to parse
    istringstream streamToScan(inPut);
    
    // switch the scanners input to use this stream
    m_scanner.switchStreams(streamToScan);
    
    // parse the input
    parse();

    return m_lastParse;
}

void Parser::saveTree(Node* tree) {
    m_lastParse = tree;
}

void Parser::reset() {
    cout << "There was an error parsing: " << toParse << endl;
}

void Parser::reset2() {
    cout << "There was an error (in reset2) parsing: " << toParse << endl;
}

Node* Parser::makeNode(nodeType type, Node* lhs, Node* rhs) {

    if (type == nodeType::VARIABLE) {
        QString st = QString::fromStdString(m_scanner.getVarable());
        return new NodeLeaf(st);
    } else if (type == nodeType::NUMBER) {
        QString st = QString::fromStdString(m_scanner.matched());
        return new NodeLeaf(st);
    } else if (type == nodeType::PERCENT) {
        return makeOneOperatorNode(new NodePercent(), lhs);
    } else if (type == nodeType::TIMES) {
        return makeTwoOperatorNode(new NodeTimes(), lhs, rhs);
    } else if (type == nodeType::PLUS) {
        return makeTwoOperatorNode(new NodePlus(), lhs, rhs);
    } else if (type == nodeType::MINUS) {
        return makeTwoOperatorNode(new NodeMinus(), lhs, rhs);
    } else if (type == nodeType::DIVIDE) {
        return makeTwoOperatorNode(new NodeDivide(), lhs, rhs);
    } else if (type == nodeType::EQUALS) {
        return makeTwoOperatorNode(new NodeEqual(), lhs, rhs);
    } else {
        // error 
        Q_ASSERT_X(0, "", "unknown node type");
        return new NodeEqual(); // to save compiler warning
    }
}

Node* Parser::makeTwoOperatorNode(Node* newNode, Node* lhs, Node* rhs) {
    if (lhs == 0 or lhs == nullptr) {
        lhs = new NodeLeaf();
    }

    if (rhs == 0 or rhs == nullptr) {
        rhs = new NodeLeaf();
    }
    Q_ASSERT_X(newNode != 0 and newNode != nullptr, "", "newNode is null");
    Q_ASSERT_X(lhs != 0 and lhs != nullptr, "", "lhs is null");
    Q_ASSERT_X(rhs != 0 and rhs != nullptr, "", "rhs is null");

    newNode->setLeftChild(lhs);
    newNode->setRightChild(rhs);
    return newNode;
}

Node* Parser::makeOneOperatorNode(Node* newNode, Node* lhs) {
    if (lhs == 0 or lhs == nullptr) {
        lhs = new NodeLeaf();
    }
    Q_ASSERT_X(newNode != 0 and newNode != nullptr, "", "newNode is null");
    Q_ASSERT_X(lhs != 0 and lhs != nullptr, "", "lhs is null");

    newNode->setSingleChild(lhs);
    return newNode;
}

Node* Parser::makeNodeParentheses(Node* childNode, bool leftPar, bool rightPar) {
    if (childNode == 0 or childNode == nullptr) {
        childNode = new NodeLeaf();
    }
    Q_ASSERT_X(childNode != 0 and childNode != nullptr, "", "childNode is null");
    Node * parNode = new NodeParentheses(leftPar,rightPar);
    parNode->setSingleChild(childNode);
    return parNode;
}